﻿using DevExpress.Blazor;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor;
using DevExpress.ExpressApp.Blazor.Components.Models;
using DevExpress.ExpressApp.Blazor.Services;
using DevExpress.ExpressApp.Blazor.Templates;
using DevExpress.ExpressApp.Blazor.Templates.Toolbar.ActionControls;
using DevExpress.ExpressApp.Templates;
using DevExpress.ExpressApp.Templates.ActionControls;
using DevExpress.Persistent.Base;
using DevExpress.Utils.CommonDialogs.Internal;
using DevExpress.Xpo;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace EasyXaf.BlazorTabbedMdi;

public class MdiViewWindowTemplate : WindowTemplateBase, ISupportActionsToolbarVisibility, ISelectionDependencyToolbar, IMdiFrameTemplate
{
    private PropertyInfo _viewPropertyInfo;
    private MethodInfo _onViewChangedMethodInfo;

    private readonly List<View> _disposeableViews = new();
    private readonly List<Window> _disposeableWindows = new();

    private readonly IUnsavedChangesConfirmationService _confirmationService;

    protected Window ViewWindow { get; }

    public IServiceProvider ServiceProvider => Application.ServiceProvider;

    public BlazorApplication Application => (BlazorApplication)ViewWindow.Application;

    public bool IsMobile { get; set; }

    public bool IsWindowKeepOpen { get; set; }

    public virtual bool CanWindowKeepOpen => IsWindowKeepOpen;

    public virtual bool HasUnsavedChanges
    {
        get
        {
            if (View?.CurrentObject != null)
            {
                if (View.ObjectSpace.IsNewObject(View.CurrentObject))
                {
                    return PersistentBase.GetModificationsStore(View.CurrentObject).HasModifications();
                }
            }
            return View?.ObjectSpace?.IsModified == true;
        }
    }

    public List<View> DisposeableViews => _disposeableViews;

    public List<Window> DisposeableWindows => _disposeableWindows;

    public bool IsActionsToolbarVisible { get; private set; }

    public DxToolbarAdapter Toolbar { get; }

    public DxToolbarAdapter SecondToolbar { get; }

    public event EventHandler StateChanged;

    public MdiViewWindowTemplate(Window window)
    {
        IsActionsToolbarVisible = true;

        Toolbar = new DxToolbarAdapter(new DxToolbarModel());
        Toolbar.AddActionContainer(nameof(PredefinedCategory.ObjectsCreation));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.RecordsNavigation), ToolbarItemAlignment.Right);
        Toolbar.AddActionContainer(nameof(PredefinedCategory.SaveOptions), ToolbarItemAlignment.Right, isDropDown: true, defaultActionId: "SaveAndNew", autoChangeDefaultAction: true);
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Save), ToolbarItemAlignment.Right);
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Close));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.UndoRedo));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Edit));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.RecordEdit));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.View));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Reports));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Search));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Filters));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.FullTextSearch));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Tools));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Export));
        Toolbar.AddActionContainer(nameof(PredefinedCategory.Unspecified));

        SecondToolbar = new DxToolbarAdapter(new DxToolbarModel());
        SecondToolbar.AddActionContainer("Toolbar2");

        ViewWindow = window;
        ViewWindow.ViewChanging += Window_ViewChanging;

        _confirmationService = ServiceProvider.GetRequiredService<IUnsavedChangesConfirmationService>();
    }

    protected virtual void SetView(View view)
    {
        _viewPropertyInfo ??= typeof(FrameTemplate).GetProperty(nameof(View));
        _viewPropertyInfo.SetValue(this, view);
    }

    protected virtual void OnViewChanged()
    {
        _onViewChangedMethodInfo ??= typeof(FrameTemplate).GetMethod(nameof(OnViewChanged), BindingFlags.NonPublic | BindingFlags.Instance);
        _onViewChangedMethodInfo.Invoke(this, null);
    }

    protected virtual void OnStateChanged()
    {
        StateChanged?.Invoke(this, EventArgs.Empty);
    }

    public Task<DialogResult> ShowConfirmationDialogAsync()
    {
        return (Task<DialogResult>)_confirmationService.GetType()
            .GetMethod(nameof(ShowConfirmationDialogAsync), BindingFlags.NonPublic | BindingFlags.Instance)
            .Invoke(_confirmationService, null);
    }

    protected virtual void Window_ViewChanging(object sender, ViewChangingEventArgs e)
    {
        if (CanWindowKeepOpen)
        {
            e.DisposeOldView = false;
        }
    }

    protected override IEnumerable<IActionControlContainer> GetActionControlContainers()
    {
        var containers = new List<IActionControlContainer>();
        containers.AddRange(Toolbar.ActionContainers);
        containers.AddRange(SecondToolbar.ActionContainers);
        return containers;
    }

    protected override RenderFragment CreateComponent() => MdiViewWindowTemplateComponent.Create(this);

    protected override void BeginUpdate()
    {
        base.BeginUpdate();
        ((ISupportUpdate)Toolbar).BeginUpdate();
    }

    protected override void EndUpdate()
    {
        ((ISupportUpdate)Toolbar).EndUpdate();
        base.EndUpdate();
    }

    void ISupportActionsToolbarVisibility.SetVisible(bool isVisible) => IsActionsToolbarVisible = isVisible;
}
